﻿using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using ActiveDirectoryService.Library.Constants;
using ActiveDirectoryService.Library.Converters;
using ActiveDirectoryService.Library.DataContracts;
using ActiveDirectoryService.Library.Entities;
using ActiveDirectoryService.Library.Enums;
using ActiveDirectoryService.Library.ExtensionMethods;

namespace ActiveDirectoryService.Library.Services
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceKnownType(typeof(GroupTypes))]
    public class UserService : IUserService
    {
        #region Private Fields

        private readonly ILightWeightDirectoryAccessService<ADUser> m_ActiveDirectoryUserService;
        private readonly ILightWeightDirectoryAccessService<ADGroup> m_ActiveDirectoryGroupService;
        private readonly IConverter m_Factory;

        #endregion


        #region Constructor

        public UserService()
            : this(new LightWeightDirectoryAccessService<ADUser>(),
                   new LightWeightDirectoryAccessService<ADGroup>(),
                   new Converter()) { }

        public UserService(ILightWeightDirectoryAccessService<ADUser> activeDirectoryUserService,
                           ILightWeightDirectoryAccessService<ADGroup> activeDirectoryGroupService,
                           IConverter factory)
        {
            m_ActiveDirectoryUserService = activeDirectoryUserService;
            m_ActiveDirectoryGroupService = activeDirectoryGroupService;
            m_Factory = factory;
        }

        #endregion

        #region Public Methods

        public IList<User> GetUsers(User filter, char separator)
        {
            var adFilter = m_Factory.Convert(filter);

            var results = m_ActiveDirectoryUserService.CreateQuery(adFilter, ActiveDirectoryFilters.Users, separator)
                                                  .Where(u => !string.IsNullOrEmpty(u.SipAddress));

            return results.Select(m_Factory.Convert).ToList();
        }


        public IList<User> GetMembersOfGroup(Group group)
        {
            var memberOfFilter = string.Format(ActiveDirectoryFilters.MembersOfDistributionGroup,
                                               group.DistinguishedName);

            var members = m_ActiveDirectoryUserService.CreateQuery((ADUser)null, memberOfFilter);

            var temp = members.Where(u => !string.IsNullOrEmpty(u.SipAddress))
                                                      .Select(m_Factory.Convert).ToList();

            return temp;
        }

        public IList<Group> GetDistributionGroups()
        {
            var adGroups = m_ActiveDirectoryGroupService.CreateQuery((ADGroup)null, ActiveDirectoryFilters.DistributionGroup);

            var groups = adGroups.Select(m_Factory.Convert).ToList();

            return groups;
        }

        public IList<Group> GetDistributionsGroupForUnit(string organisationUnit)
        {
            var adGroups = m_ActiveDirectoryGroupService.CreateQuery(organisationUnit, null, ActiveDirectoryFilters.DistributionGroup);

            var groups = adGroups.Select(m_Factory.Convert).ToList();

            return groups;
        }

        #endregion

    }
}